import { Request, Response, NextFunction } from 'express';
import ApiResponse from '@/utils/api/api-response.util';
import { isEmpty, isValidStatus } from '../common/validation.util';
import menuService from '@/services/system/menu.service';
import { getLogger } from '@/utils/logger';

const logger = getLogger('menu-validator', { console: false });
const consoleLogger = getLogger('menu-validator');

/**
 * 验证菜单类型是否有效
 * @param menuType 菜单类型
 * @returns 是否有效
 */
const isValidMenuType = (menuType: string): boolean => {
  return ['M', 'C', 'F'].includes(menuType);
};

/**
 * 验证可见性是否有效
 * @param visible 可见性
 * @returns 是否有效
 */
const isValidVisible = (visible: string): boolean => {
  return ['0', '1'].includes(visible);
};

/**
 * 验证菜单创建参数
 */
export const validateMenuCreate = async (req: Request, res: Response, next: NextFunction) => {
  try {
    const { menuName, menuType, parentId } = req.body;
    
    // 菜单名称验证
    if (isEmpty(menuName)) {
      return ApiResponse.error(res, '菜单名称不能为空', 400);
    }
    
    // 菜单类型验证
    if (isEmpty(menuType)) {
      return ApiResponse.error(res, '菜单类型不能为空', 400);
    }
    
    if (!isValidMenuType(menuType)) {
      return ApiResponse.error(res, '菜单类型无效，必须为M、C或F', 400);
    }
    
    // 路由地址验证（目录和菜单必须有路由地址）
    if ((menuType === 'M' || menuType === 'C') && isEmpty(req.body.path)) {
      return ApiResponse.error(res, '路由地址不能为空', 400);
    }
    
    // 组件路径验证（菜单必须有组件路径）
    if (menuType === 'C' && isEmpty(req.body.component)) {
      return ApiResponse.error(res, '组件路径不能为空', 400);
    }
    
    // 校验菜单名称是否唯一
    const isUnique = await menuService.checkMenuNameUnique(
      menuName,
      parentId || 0
    );
    if (!isUnique) {
      consoleLogger.warn('新增菜单失败: 菜单名称已存在', { menuName });
      return ApiResponse.error(res, '新增菜单失败，菜单名称已存在', 400);
    }
    
    // 状态验证
    if (req.body.status && !isValidStatus(req.body.status)) {
      return ApiResponse.error(res, '状态值无效', 400);
    }
    
    // 可见性验证
    if (req.body.visible && !isValidVisible(req.body.visible)) {
      return ApiResponse.error(res, '可见性值无效', 400);
    }
    
    logger.debug('菜单创建参数验证通过');
    next();
    return;
  } catch (error) {
    consoleLogger.error(`菜单创建验证失败: ${error instanceof Error ? error.message : String(error)}`);
    return ApiResponse.error(res, '参数验证失败', 500);
  }
};

/**
 * 验证菜单更新参数
 */
export const validateMenuUpdate = async (req: Request, res: Response, next: NextFunction) => {
  try {
    const { menuId, menuName, menuType, parentId } = req.body;
    
    if (isEmpty(menuId) || isNaN(parseInt(menuId))) {
      return ApiResponse.error(res, '菜单ID无效', 400);
    }
    
    // 菜单名称验证
    if (isEmpty(menuName)) {
      return ApiResponse.error(res, '菜单名称不能为空', 400);
    }
    
    // 菜单类型验证
    if (isEmpty(menuType)) {
      return ApiResponse.error(res, '菜单类型不能为空', 400);
    }
    
    if (!isValidMenuType(menuType)) {
      return ApiResponse.error(res, '菜单类型无效，必须为M、C或F', 400);
    }
    
    // 路由地址验证（目录和菜单必须有路由地址）
    if ((menuType === 'M' || menuType === 'C') && isEmpty(req.body.path)) {
      return ApiResponse.error(res, '路由地址不能为空', 400);
    }
    
    // 组件路径验证（菜单必须有组件路径）
    if (menuType === 'C' && isEmpty(req.body.component)) {
      return ApiResponse.error(res, '组件路径不能为空', 400);
    }
    
    // 校验菜单是否存在
    const existMenu = await menuService.selectMenuById(menuId);
    if (!existMenu) {
      logger.warn('修改菜单失败: 菜单不存在', { menuId });
      return ApiResponse.error(res, '修改菜单失败，菜单不存在', 404);
    }
    
    // 不能将自己设为父菜单
    if (menuId === parentId) {
      return ApiResponse.error(res, '不能选择自己作为父菜单', 400);
    }
    
    // 校验菜单名称是否唯一
    const isUnique = await menuService.checkMenuNameUnique(
      menuName,
      parentId || 0,
      menuId
    );
    if (!isUnique) {
      logger.warn('修改菜单失败: 菜单名称已存在', { menuName });
      return ApiResponse.error(res, '修改菜单失败，菜单名称已存在', 400);
    }
    
    // 状态验证
    if (req.body.status && !isValidStatus(req.body.status)) {
      return ApiResponse.error(res, '状态值无效', 400);
    }
    
    // 可见性验证
    if (req.body.visible && !isValidVisible(req.body.visible)) {
      return ApiResponse.error(res, '可见性值无效', 400);
    }
    
    logger.debug('菜单更新参数验证通过');
    next();
    return;
  } catch (error) {
    consoleLogger.error(`菜单更新验证失败: ${error instanceof Error ? error.message : String(error)}`);
    return ApiResponse.error(res, '参数验证失败', 500);
  }
};

/**
 * 验证删除菜单参数
 */
export const validateMenuRemove = async (req: Request, res: Response, next: NextFunction) => {
  try {
    const menuId = Number(req.params.menuId);
    
    if (isNaN(menuId) || menuId <= 0) {
      return ApiResponse.error(res, '菜单ID无效', 400);
    }
    
    // 检查是否存在子菜单
    const hasChild = await menuService.hasChildByMenuId(menuId);
    if (hasChild) {
      return ApiResponse.error(res, '存在子菜单，不允许删除', 400);
    }
    
    // 检查菜单是否已分配角色
    const hasRole = await menuService.checkMenuExistRole(menuId);
    if (hasRole) {
      return ApiResponse.error(res, '菜单已分配角色，不允许删除', 400);
    }
    
    logger.debug('删除菜单参数验证通过');
    next();
    return;
  } catch (error) {
    consoleLogger.error(`删除菜单验证失败: ${error instanceof Error ? error.message : String(error)}`);
    return ApiResponse.error(res, '参数验证失败', 500);
  }
}; 